Step 3: Configuration and Cache Variables ========================================= CMake projects often have some project-specific configuration variables which users and packagers are interested in. CMake has many ways that an invoking user or process can communicate these configuration choices, but the most fundamental of them are :option:`-D ` flags. In this step we'll explore the ins and out of how to provide project configuration options from within a CML, and how to invoke CMake to take advantage of configuration options provided by both CMake and individual projects. Background ^^^^^^^^^^ If we had a CMake project for compression software which supported multiple compression algorithms, we might want to let the packager of the project decide which algorithms to enable when they build our software. We can do so by consuming variables set via :option:`-D ` flags. .. code-block:: cmake if(COMPRESSION_SOFTWARE_USE_ZLIB) message("I will use Zlib!") # ... endif() if(COMPRESSION_SOFTWARE_USE_ZSTD) message("I will use Zstd!") # ... endif() .. code-block:: console $ cmake -B build \ -DCOMPRESSION_SOFTWARE_USE_ZLIB=ON \ -DCOMPRESSION_SOFTWARE_USE_ZSTD=OFF ... I will use Zlib! Of course, we will want to provide reasonable defaults for these configuration choices, and a way to communicate the purpose of a given option. This function is provided by the :command:`option` command. .. code-block:: cmake option(COMPRESSION_SOFTWARE_USE_ZLIB "Support Zlib compression" ON) option(COMPRESSION_SOFTWARE_USE_ZSTD "Support Zstd compression" ON) if(COMPRESSION_SOFTWARE_USE_ZLIB) # Same as before # ... .. code-block:: console $ cmake -B build \ -DCOMPRESSION_SOFTWARE_USE_ZLIB=OFF ... I will use Zstd! The names created by :option:`-D ` flags and :command:`option` are not normal variables, they are **cache** variables. Cache variables are globally visible variables which are *sticky*, their value is difficult to change after it is initially set. In fact they are so sticky that, in project mode, CMake will save and restore cache variables across multiple configurations. If a cache variable is set once, it will remain until another :option:`-D ` flag preempts the saved variable. .. note:: CMake itself has dozens of normal and cache variables used for configuration. These are documented at :manual:`cmake-variables(7)` and operate in the same manner as project-provided variables for configuration. :command:`set` can also be used to manipulate cache variables, but will not change a variable which has already been created. .. code-block:: cmake set(StickyCacheVariable "I will not change" CACHE STRING "") set(StickyCacheVariable "Overwrite StickyCache" CACHE STRING "") message("StickyCacheVariable: ${StickyCacheVariable}") .. code-block:: console $ cmake -B build ... StickyCacheVariable: I will not change Because :option:`-D ` flags are processed before any project commands, they take precedence for setting the value of a cache variable. .. code-block:: console $ cmake -B build \ -DStickyCacheVariable="Commandline always wins" ... StickyCacheVariable: Commandline always wins While cache variables cannot ordinarily be changed, they can be *shadowed* by normal variables. We can observe this by :command:`set`'ing a variable to have the same name as a cache variable, and then using :command:`unset` to remove the normal variable. .. code-block:: cmake set(ShadowVariable "In the shadows" CACHE STRING "") set(ShadowVariable "Hiding the cache variable") message("ShadowVariable: ${ShadowVariable}") unset(ShadowVariable) message("ShadowVariable: ${ShadowVariable}") .. code-block:: console $ cmake -B build ... ShadowVariable: Hiding the cache variable ShadowVariable: In the shadows .. note:: :ref:`Script mode